#include "fd_manager.h"
#include "hook.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>


namespace framework
{

//通过文件句柄构造FdCtx
FDCtx::FDCtx(int fd)
    :m_isInit(false)
    ,m_isSocket(false)
    ,m_sysNonblock(false)
    ,m_userNonblock(false)
    ,m_isClosed(false)
    ,m_fd(fd)
    ,m_recvTimeout(-1)
    ,m_sendTimeout(-1) 
{
    init();
}

FDCtx::~FDCtx()
{

}

//设置超时时间
//type 类型SO_RCVTIMEO(读超时), SO_SNDTIMEO(写超时)
//v 时间  毫秒
void FDCtx::setTimeout(int type, uint64_t v)
{
    //SO_RCVTIMEO： 用来设置socket接收数据的超时时间
    //SO_SNDTIMEO： 用来设置socket发送数据的超时时间；
    if(type == SO_RCVTIMEO)
    {
        m_recvTimeout = v;
    }
    else
    {
        m_sendTimeout = v;
    }
}


//获取超时时间
//type 类型SO_RCVTIMEO(读超时), SO_SNDTIMEO(写超时)
//返回超时时间  毫秒
uint64_t FDCtx::getTimeout(int type)
{
    if(type == SO_RCVTIMEO)
    {
        return m_recvTimeout;
    }

    return m_sendTimeout;
}

//初始化
bool FDCtx::init()
{
    if(m_isInit)
    {
        return true;
    }
    m_recvTimeout = -1;
    m_sendTimeout = -1;

    struct stat fd_stat;
    //获取对应文件描述符的文件状态信息
    if(-1 == fstat(m_fd, &fd_stat))
    {
        m_isInit = false;
        m_isSocket = false;
    }
    else
    {
        m_isInit = true;
        //判断m_fd是否为socket类型
        m_isSocket = S_ISSOCK(fd_stat.st_mode);
    }

    if(m_isSocket)
    {
        // 获取文件描述符的标志和访问模式
        int flags = fcntl_f(m_fd, F_GETFL, 0);
        //如果不是非阻塞模式
        if(!(flags & O_NONBLOCK))
        {
            //将描述符设置为非阻塞
            fcntl_f(m_fd, F_SETFL, flags | O_NONBLOCK);
            m_sysNonblock = true;
        }
    }
    else
    {
        m_sysNonblock = false;
    }

    m_userNonblock = false;
    m_isClosed = false;

    return m_isInit;
}







FdManager::FdManager()
{
    m_datas.resize(64);
}

//获取/创建文件句柄类FdCtx
//fd 文件句柄
//auto_create 是否自动创建
//返回对应文件句柄类FdCtx::ptr
FDCtx::ptr FdManager::get(int fd, bool auto_create)
{
    if(fd == -1)
    {
        return nullptr;
    }

    RWMutexType::ReadLock lock(m_mutex);
    if((int)m_datas.size() <= fd)
    {
        //如果当前没有fd，并且不自动创建则返回null
        if(auto_create == false)
        {
            return nullptr;
        }
    }
    else
    {
        //如果当前有fd直接返回已有fd
        //如果没有fd并且不自动创建则返回nulls
        if(m_datas[fd] || !auto_create)
        {
            return m_datas[fd];
        }
    }
    lock.unlock();

    //如果当前没有对应的fd,则新创建fd
    RWMutexType::WriteLock lock2(m_mutex);
    FDCtx::ptr ctx(new FDCtx(fd));
    if(fd >= (int)m_datas.size())
    {
        m_datas.resize(fd * 1.5);
    }
    m_datas[fd] = ctx;
    return ctx;

}

//删除文件句柄类
void FdManager::del(int fd)
{
    RWMutexType::WriteLock lock(m_mutex);
    if((int)m_datas.size() <= fd)
    {
        return;
    }
    m_datas[fd].reset();
}


}

